/*!
 * @file        usb_power.c
 *
 * @brief       USB power management       
 *
 * @version     V1.0.0
 *
 * @date        2020-4-30
 *
 */
#include "usb.h"
#include "usb_power.h"
#include "apm32f10x_pmu.h"

/*!
 * @brief       USB Power on
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void USB_PowerOn(void)
{
    USB_ResetPowerDown();

    USB_SetForceReset();
    USB_ResetForceReset();
    
    USB_DisableInterrupt(USB_INT_ALL);
    USB_ClearIntFlag(USB_INT_ALL);
    
    USB_EnableInterrupt(USB_INT_SOURCE);
}

/*!
 * @brief       USB Power off
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void USB_PowerOff(void)
{
    USB_DisableInterrupt(USB_INT_ALL);
    USB_ClearIntFlag(USB_INT_ALL);
    USB_SetRegCTRL(0X03);
}

/*!
 * @brief       USB Suspend
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void USB_Suspend(void)
{
    uint8_t i;
    uint16_t bakEP[8];
    uint32_t bakPwrCR;
    uint32_t tmp;
    
    for(i = 0; i < 8; i++)
    {
        bakEP[i] = (uint16_t)USB->EP[i].EP;
    }

    USB_EnableInterrupt(USB_INT_RESET);
    
    USB_SetForceReset();
    USB_ResetForceReset();

    while(USB_ReadIntFlag(USB_INT_RESET) == RESET);

    for(i = 0; i < 8; i++)
    {
        USB->EP[i].EP = bakEP[i];
    }

    USB_SetForceSuspend();
    USB_SetLowerPowerMode();

    bakPwrCR = PMU->CTRL;
    tmp = PMU->CTRL;
    tmp &= (uint32_t)0xfffffffc;
    tmp |= PMU_Regulator_LowPower; 
    PMU->CTRL = tmp;

    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    if(USB_ReadIntFlag(USB_INT_WAKEUP) == RESET)
    {
        __WFI();
        SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
    }
    else
    {
        USB_ClearIntFlag(USB_INT_WAKEUP);
        USB_ResetForceSuspend();
        PMU->CTRL = bakPwrCR;
        SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
    }
}


/*!
 * @brief       Resume
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void USB_Resume(void)
{
    USB_ResetLowerPowerMode();

    SystemInit();
    
    USB_SetRegCTRL(USB_INT_SOURCE);
}
